/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */
 
#ifndef TYPESTACK_H_
#define TYPESTACK_H_

#ifdef __cplusplus
extern "C" {
#endif

/* forward declarations */

typedef struct type_item type_item;

typedef struct type_list
{
	type_item * head;
	type_item * tail;
	int count;
} type_list;

/* type_item structure and methods. */

typedef union type_data
{
		int8_t s8;
		uint8_t u8;
		int16_t s16;
		uint16_t u16;
		int32_t s32;
		uint32_t u32;
		int64_t s64;
		uint64_t u64;
		void * ptr;
		type_list list;
		type_buffer buffer;
} 
type_data;




typedef struct type_item
{
	struct type_item * next;
	type_element * type;
	type_data data;
} type_stack_item;

type_item * type_item_alloc();
void type_item_free( type_item * item );

#define type_item_next( item ) (item)->next;
#define type_item_type( item ) (item)->type;

#define type_item_set_u8( item, t, b ) (item)->type = (t); (item)->data.u8 = (b)
#define type_item_get_u8( item ) ((item)->data.u8)
#define type_item_set_s8( item, t, b ) (item)->type = (t); (item)->data.s8 = (b)
#define type_item_get_s8( item ) ((item)->data.s8)

#define type_item_set_u16( item, t, s ) (item)->type = (t); (item)->data.u16 = (s)
#define type_item_get_u16( item ) ((item)->data.u16)
#define type_item_set_s16( item, t, s ) (item)->type = (t); (item)->data.s16 = (s)
#define type_item_get_s16( item ) ((item)->data.s16)

#define type_item_set_u32( item, t, i ) (item)->type = (t); (item)->data.u32 = (i)
#define type_item_get_u32( item ) ((item)->data.u32)
#define type_item_set_s32( item, t, i ) (item)->type = (t); (item)->data.s32 = (i)
#define type_item_get_s32( item ) ((item)->data.s32)

#define type_item_set_u64( item, t, l ) (item)->type = (t); (item)->data.u64 = (l)
#define type_item_get_u64( item ) ((item)->data.u64)
#define type_item_set_s64( item, t, l ) (item)->type = (t); (item)->data.s64 = (l)
#define type_item_get_s64( item ) ((item)->data.s64)

#define type_item_set_ptr( item, t, p ) (item)->type = (t); (item)->data.ptr = (p)
#define type_item_get_ptr( item ) ((item)->data.ptr)

#define type_item_get_list( item ) (&((item)->data.list))

/* type_list structure and functions. */




#define type_list_head( list ) ((list)->head)
#define type_list_tail( list ) ((list)->tail)
#define type_list_size( list ) ((list)->count)


/* type_stack struture and functions. */

typedef struct type_stack
{
	type_item * top;
	int count;
} type_stack;



#define type_stack_size( stack ) ((stack)->count)
#define type_stack_is_empty( stack ) ((stack)->count)>0?0:1


#define type_stack_type( stack ) ((stack)->top->type)

#define type_stack_set_u8( stack, t, b ) (stack)->top->type = (t); (stack)->top->data.u8 = (b)
#define type_stack_get_u8( stack ) ((stack)->top->data.u8)
#define type_stack_set_s8( stack, t, b ) (stack)->top->type = (t); (stack)->top->data.s8 = (b)
#define type_stack_get_s8( stack ) ((stack)->top->data.s8)

#define type_stack_set_u16( stack, t, s ) (stack)->top->type = (t); (stack)->top->data.u16 = (s)
#define type_stack_get_u16( stack ) ((stack)->top->data.u16)
#define type_stack_set_s16( stack, t, s ) (stack)->top->type = (t); (stack)->top->data.s16 = (s)
#define type_stack_get_s16( stack ) ((stack)->top->data.s16)

#define type_stack_set_u32( stack, t, i ) (stack)->top->type = (t); (stack)->top->data.u32 = (i)
#define type_stack_get_u32( stack ) ((stack)->top->data.u32)
#define type_stack_set_s32( stack, t, i ) (stack)->top->type = (t); (stack)->top->data.s32 = (i)
#define type_stack_get_s32( stack ) ((stack)->top->data.s32)

#define type_stack_set_u64( stack, t, l ) (stack)->top->type = (t); (stack)->top->data.u64 = (l)
#define type_stack_get_u64( stack ) ((stack)->top->data.u64)
#define type_stack_set_s64( stack, t, l ) (stack)->top->type = (t); (stack)->top->data.s64 = (l)
#define type_stack_get_s64( stack ) ((stack)->top->data.s64)

#define type_stack_set_ptr( stack, t, p ) (stack)->top->type = (t); (stack)->top->data.ptr = (p)
#define type_stack_get_ptr( stack ) ((stack)->top->data.ptr)

#define type_stack_get_list( stack ) (&((stack)->top->data.list))

#ifdef INLINE
	#include "typestackinline.c"
#else
	extern void type_list_init( type_list * list );
	extern void type_list_add_head( type_list * list, type_item * item );
	extern void type_list_add_tail( type_list * list, type_item * item );
	extern type_item * type_list_remove_head( type_list * list );
	extern void type_list_clear( type_list * list );
	extern void type_stack_init( type_stack * stack );
	extern void type_stack_push( type_stack * stack );
	extern type_item * type_stack_remove( type_stack * stack );
	extern void type_stack_pop( type_stack * stack );
	extern void type_stack_clear( type_stack * stack );
#endif

#ifdef __cplusplus
}
#endif

#endif
